package org.jetlinks.pro.device.service.task;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Generated;
import lombok.Getter;
import lombok.Setter;
import org.jetlinks.core.enums.ErrorCode;
import org.jetlinks.core.exception.DeviceOperationException;
import org.jetlinks.core.message.DeviceMessage;
import org.jetlinks.core.message.DeviceMessageReply;
import org.jetlinks.pro.PropertyConstants;
import org.jetlinks.pro.device.enums.TaskState;

import java.util.Map;

@Getter
@Setter
@Generated
public class DeviceMessageResponse {

    @Schema(description = "任务ID")
    private String id;

    @Schema(description = "设备ID")
    private String deviceId;

    @Schema(description = "消息ID")
    private String messageId;

    @Schema(description = "上行回复内容")
    private Map<String, Object> upstream;

    @Schema(description = "是否成功")
    private boolean success;

    @Schema(description = "错误信息")
    private String error;

    @Schema(description = "错误码")
    private String errorCode;

    @Schema(description = "指令状态")
    private TaskState state;

    @Schema(description = "响应时间")
    private long replyTime;

    @Schema(description = "请求时间")
    private long sendTime;

    public static DeviceMessageResponse of(DeviceMessage downstream, DeviceMessageReply reply) {
        DeviceMessageResponse response = new DeviceMessageResponse();
        response.setDeviceId(reply.getDeviceId());
        response.setMessageId(reply.getMessageId());
        response.setSuccess(reply.isSuccess());
        response.setError(reply.getMessage());
        response.setErrorCode(reply.getCode());
        response.setUpstream(reply.toJson());
        response.setSendTime(downstream.getTimestamp());
        response.setReplyTime(reply.getTimestamp());
        reply.getHeader(PropertyConstants.taskId).ifPresent(response::setId);
        if (reply.isSuccess()) {
            response.setState(TaskState.success);
        } else {
            response.setState(TaskState.fail);
        }
        return response;
    }

    public static DeviceMessageResponse of(DeviceMessage downstream, Throwable error) {
        DeviceMessageResponse response = new DeviceMessageResponse();
        downstream.getHeader(PropertyConstants.taskId).ifPresent(response::setId);
        response.setDeviceId(downstream.getDeviceId());
        response.setMessageId(downstream.getMessageId());
        response.setSuccess(false);
        response.setState(TaskState.sendError);
        response.setSendTime(downstream.getTimestamp());
        response.setReplyTime(System.currentTimeMillis());
        response.setError(error.getLocalizedMessage());
        if (error instanceof DeviceOperationException) {
            response.setErrorCode(((DeviceOperationException) error).getCode().name());
        } else {
            response.setErrorCode(ErrorCode.SYSTEM_ERROR.name());
        }
        return response;
    }
}
